from datetime import datetime

from sentry.issues.escalating.escalating_issues_alg import generate_issue_forecast

START_TIME = datetime.fromisoformat("2022-07-27T00:00:00+00:00")

SEVEN_DAY_INPUT_INTERVALS = [
    "2022-07-20T00:00:00+00:00",
    "2022-07-20T01:00:00+00:00",
    "2022-07-20T02:00:00+00:00",
    "2022-07-20T03:00:00+00:00",
    "2022-07-20T04:00:00+00:00",
    "2022-07-20T05:00:00+00:00",
    "2022-07-20T06:00:00+00:00",
    "2022-07-20T07:00:00+00:00",
    "2022-07-20T08:00:00+00:00",
    "2022-07-20T09:00:00+00:00",
    "2022-07-20T10:00:00+00:00",
    "2022-07-20T11:00:00+00:00",
    "2022-07-20T12:00:00+00:00",
    "2022-07-20T13:00:00+00:00",
    "2022-07-20T14:00:00+00:00",
    "2022-07-20T15:00:00+00:00",
    "2022-07-20T16:00:00+00:00",
    "2022-07-20T17:00:00+00:00",
    "2022-07-20T18:00:00+00:00",
    "2022-07-20T19:00:00+00:00",
    "2022-07-20T20:00:00+00:00",
    "2022-07-20T21:00:00+00:00",
    "2022-07-20T22:00:00+00:00",
    "2022-07-20T23:00:00+00:00",
    "2022-07-21T00:00:00+00:00",
    "2022-07-21T01:00:00+00:00",
    "2022-07-21T02:00:00+00:00",
    "2022-07-21T03:00:00+00:00",
    "2022-07-21T04:00:00+00:00",
    "2022-07-21T05:00:00+00:00",
    "2022-07-21T06:00:00+00:00",
    "2022-07-21T07:00:00+00:00",
    "2022-07-21T08:00:00+00:00",
    "2022-07-21T09:00:00+00:00",
    "2022-07-21T10:00:00+00:00",
    "2022-07-21T11:00:00+00:00",
    "2022-07-21T12:00:00+00:00",
    "2022-07-21T13:00:00+00:00",
    "2022-07-21T14:00:00+00:00",
    "2022-07-21T15:00:00+00:00",
    "2022-07-21T16:00:00+00:00",
    "2022-07-21T17:00:00+00:00",
    "2022-07-21T18:00:00+00:00",
    "2022-07-21T19:00:00+00:00",
    "2022-07-21T20:00:00+00:00",
    "2022-07-21T21:00:00+00:00",
    "2022-07-21T22:00:00+00:00",
    "2022-07-21T23:00:00+00:00",
    "2022-07-22T00:00:00+00:00",
    "2022-07-22T01:00:00+00:00",
    "2022-07-22T02:00:00+00:00",
    "2022-07-22T03:00:00+00:00",
    "2022-07-22T04:00:00+00:00",
    "2022-07-22T05:00:00+00:00",
    "2022-07-22T06:00:00+00:00",
    "2022-07-22T07:00:00+00:00",
    "2022-07-22T08:00:00+00:00",
    "2022-07-22T09:00:00+00:00",
    "2022-07-22T10:00:00+00:00",
    "2022-07-22T11:00:00+00:00",
    "2022-07-22T12:00:00+00:00",
    "2022-07-22T13:00:00+00:00",
    "2022-07-22T14:00:00+00:00",
    "2022-07-22T15:00:00+00:00",
    "2022-07-22T16:00:00+00:00",
    "2022-07-22T17:00:00+00:00",
    "2022-07-22T18:00:00+00:00",
    "2022-07-22T19:00:00+00:00",
    "2022-07-22T20:00:00+00:00",
    "2022-07-22T21:00:00+00:00",
    "2022-07-22T22:00:00+00:00",
    "2022-07-22T23:00:00+00:00",
    "2022-07-23T00:00:00+00:00",
    "2022-07-23T01:00:00+00:00",
    "2022-07-23T02:00:00+00:00",
    "2022-07-23T03:00:00+00:00",
    "2022-07-23T04:00:00+00:00",
    "2022-07-23T05:00:00+00:00",
    "2022-07-23T06:00:00+00:00",
    "2022-07-23T07:00:00+00:00",
    "2022-07-23T08:00:00+00:00",
    "2022-07-23T09:00:00+00:00",
    "2022-07-23T10:00:00+00:00",
    "2022-07-23T11:00:00+00:00",
    "2022-07-23T12:00:00+00:00",
    "2022-07-23T13:00:00+00:00",
    "2022-07-23T14:00:00+00:00",
    "2022-07-23T15:00:00+00:00",
    "2022-07-23T16:00:00+00:00",
    "2022-07-23T17:00:00+00:00",
    "2022-07-23T18:00:00+00:00",
    "2022-07-23T19:00:00+00:00",
    "2022-07-23T20:00:00+00:00",
    "2022-07-23T21:00:00+00:00",
    "2022-07-23T22:00:00+00:00",
    "2022-07-23T23:00:00+00:00",
    "2022-07-24T00:00:00+00:00",
    "2022-07-24T01:00:00+00:00",
    "2022-07-24T02:00:00+00:00",
    "2022-07-24T03:00:00+00:00",
    "2022-07-24T04:00:00+00:00",
    "2022-07-24T05:00:00+00:00",
    "2022-07-24T06:00:00+00:00",
    "2022-07-24T07:00:00+00:00",
    "2022-07-24T08:00:00+00:00",
    "2022-07-24T09:00:00+00:00",
    "2022-07-24T10:00:00+00:00",
    "2022-07-24T11:00:00+00:00",
    "2022-07-24T12:00:00+00:00",
    "2022-07-24T13:00:00+00:00",
    "2022-07-24T14:00:00+00:00",
    "2022-07-24T15:00:00+00:00",
    "2022-07-24T16:00:00+00:00",
    "2022-07-24T17:00:00+00:00",
    "2022-07-24T18:00:00+00:00",
    "2022-07-24T19:00:00+00:00",
    "2022-07-24T20:00:00+00:00",
    "2022-07-24T21:00:00+00:00",
    "2022-07-24T22:00:00+00:00",
    "2022-07-24T23:00:00+00:00",
    "2022-07-25T00:00:00+00:00",
    "2022-07-25T01:00:00+00:00",
    "2022-07-25T02:00:00+00:00",
    "2022-07-25T03:00:00+00:00",
    "2022-07-25T04:00:00+00:00",
    "2022-07-25T05:00:00+00:00",
    "2022-07-25T06:00:00+00:00",
    "2022-07-25T07:00:00+00:00",
    "2022-07-25T08:00:00+00:00",
    "2022-07-25T09:00:00+00:00",
    "2022-07-25T10:00:00+00:00",
    "2022-07-25T11:00:00+00:00",
    "2022-07-25T12:00:00+00:00",
    "2022-07-25T13:00:00+00:00",
    "2022-07-25T14:00:00+00:00",
    "2022-07-25T15:00:00+00:00",
    "2022-07-25T16:00:00+00:00",
    "2022-07-25T17:00:00+00:00",
    "2022-07-25T18:00:00+00:00",
    "2022-07-25T19:00:00+00:00",
    "2022-07-25T20:00:00+00:00",
    "2022-07-25T21:00:00+00:00",
    "2022-07-25T22:00:00+00:00",
    "2022-07-25T23:00:00+00:00",
    "2022-07-26T00:00:00+00:00",
    "2022-07-26T01:00:00+00:00",
    "2022-07-26T02:00:00+00:00",
    "2022-07-26T03:00:00+00:00",
    "2022-07-26T04:00:00+00:00",
    "2022-07-26T05:00:00+00:00",
    "2022-07-26T06:00:00+00:00",
    "2022-07-26T07:00:00+00:00",
    "2022-07-26T08:00:00+00:00",
    "2022-07-26T09:00:00+00:00",
    "2022-07-26T10:00:00+00:00",
    "2022-07-26T11:00:00+00:00",
    "2022-07-26T12:00:00+00:00",
    "2022-07-26T13:00:00+00:00",
    "2022-07-26T14:00:00+00:00",
    "2022-07-26T15:00:00+00:00",
    "2022-07-26T16:00:00+00:00",
    "2022-07-26T17:00:00+00:00",
    "2022-07-26T18:00:00+00:00",
    "2022-07-26T19:00:00+00:00",
    "2022-07-26T20:00:00+00:00",
    "2022-07-26T21:00:00+00:00",
    "2022-07-26T22:00:00+00:00",
    "2022-07-26T23:00:00+00:00",
]

SIX_DAY_INPUT_INTERVALS = [
    "2022-07-21T00:00:00+00:00",
    "2022-07-21T01:00:00+00:00",
    "2022-07-21T02:00:00+00:00",
    "2022-07-21T03:00:00+00:00",
    "2022-07-21T04:00:00+00:00",
    "2022-07-21T05:00:00+00:00",
    "2022-07-21T06:00:00+00:00",
    "2022-07-21T07:00:00+00:00",
    "2022-07-21T08:00:00+00:00",
    "2022-07-21T09:00:00+00:00",
    "2022-07-21T10:00:00+00:00",
    "2022-07-21T11:00:00+00:00",
    "2022-07-21T12:00:00+00:00",
    "2022-07-21T13:00:00+00:00",
    "2022-07-21T14:00:00+00:00",
    "2022-07-21T15:00:00+00:00",
    "2022-07-21T16:00:00+00:00",
    "2022-07-21T17:00:00+00:00",
    "2022-07-21T18:00:00+00:00",
    "2022-07-21T19:00:00+00:00",
    "2022-07-21T20:00:00+00:00",
    "2022-07-21T21:00:00+00:00",
    "2022-07-21T22:00:00+00:00",
    "2022-07-21T23:00:00+00:00",
    "2022-07-22T00:00:00+00:00",
    "2022-07-22T01:00:00+00:00",
    "2022-07-22T02:00:00+00:00",
    "2022-07-22T03:00:00+00:00",
    "2022-07-22T04:00:00+00:00",
    "2022-07-22T05:00:00+00:00",
    "2022-07-22T06:00:00+00:00",
    "2022-07-22T07:00:00+00:00",
    "2022-07-22T08:00:00+00:00",
    "2022-07-22T09:00:00+00:00",
    "2022-07-22T10:00:00+00:00",
    "2022-07-22T11:00:00+00:00",
    "2022-07-22T12:00:00+00:00",
    "2022-07-22T13:00:00+00:00",
    "2022-07-22T14:00:00+00:00",
    "2022-07-22T15:00:00+00:00",
    "2022-07-22T16:00:00+00:00",
    "2022-07-22T17:00:00+00:00",
    "2022-07-22T18:00:00+00:00",
    "2022-07-22T19:00:00+00:00",
    "2022-07-22T20:00:00+00:00",
    "2022-07-22T21:00:00+00:00",
    "2022-07-22T22:00:00+00:00",
    "2022-07-22T23:00:00+00:00",
    "2022-07-23T00:00:00+00:00",
    "2022-07-23T01:00:00+00:00",
    "2022-07-23T02:00:00+00:00",
    "2022-07-23T03:00:00+00:00",
    "2022-07-23T04:00:00+00:00",
    "2022-07-23T05:00:00+00:00",
    "2022-07-23T06:00:00+00:00",
    "2022-07-23T07:00:00+00:00",
    "2022-07-23T08:00:00+00:00",
    "2022-07-23T09:00:00+00:00",
    "2022-07-23T10:00:00+00:00",
    "2022-07-23T11:00:00+00:00",
    "2022-07-23T12:00:00+00:00",
    "2022-07-23T13:00:00+00:00",
    "2022-07-23T14:00:00+00:00",
    "2022-07-23T15:00:00+00:00",
    "2022-07-23T16:00:00+00:00",
    "2022-07-23T17:00:00+00:00",
    "2022-07-23T18:00:00+00:00",
    "2022-07-23T19:00:00+00:00",
    "2022-07-23T20:00:00+00:00",
    "2022-07-23T21:00:00+00:00",
    "2022-07-23T22:00:00+00:00",
    "2022-07-23T23:00:00+00:00",
    "2022-07-24T00:00:00+00:00",
    "2022-07-24T01:00:00+00:00",
    "2022-07-24T02:00:00+00:00",
    "2022-07-24T03:00:00+00:00",
    "2022-07-24T04:00:00+00:00",
    "2022-07-24T05:00:00+00:00",
    "2022-07-24T06:00:00+00:00",
    "2022-07-24T07:00:00+00:00",
    "2022-07-24T08:00:00+00:00",
    "2022-07-24T09:00:00+00:00",
    "2022-07-24T10:00:00+00:00",
    "2022-07-24T11:00:00+00:00",
    "2022-07-24T12:00:00+00:00",
    "2022-07-24T13:00:00+00:00",
    "2022-07-24T14:00:00+00:00",
    "2022-07-24T15:00:00+00:00",
    "2022-07-24T16:00:00+00:00",
    "2022-07-24T17:00:00+00:00",
    "2022-07-24T18:00:00+00:00",
    "2022-07-24T19:00:00+00:00",
    "2022-07-24T20:00:00+00:00",
    "2022-07-24T21:00:00+00:00",
    "2022-07-24T22:00:00+00:00",
    "2022-07-24T23:00:00+00:00",
    "2022-07-25T00:00:00+00:00",
    "2022-07-25T01:00:00+00:00",
    "2022-07-25T02:00:00+00:00",
    "2022-07-25T03:00:00+00:00",
    "2022-07-25T04:00:00+00:00",
    "2022-07-25T05:00:00+00:00",
    "2022-07-25T06:00:00+00:00",
    "2022-07-25T07:00:00+00:00",
    "2022-07-25T08:00:00+00:00",
    "2022-07-25T09:00:00+00:00",
    "2022-07-25T10:00:00+00:00",
    "2022-07-25T11:00:00+00:00",
    "2022-07-25T12:00:00+00:00",
    "2022-07-25T13:00:00+00:00",
    "2022-07-25T14:00:00+00:00",
    "2022-07-25T15:00:00+00:00",
    "2022-07-25T16:00:00+00:00",
    "2022-07-25T17:00:00+00:00",
    "2022-07-25T18:00:00+00:00",
    "2022-07-25T19:00:00+00:00",
    "2022-07-25T20:00:00+00:00",
    "2022-07-25T21:00:00+00:00",
    "2022-07-25T22:00:00+00:00",
    "2022-07-25T23:00:00+00:00",
    "2022-07-26T00:00:00+00:00",
    "2022-07-26T01:00:00+00:00",
    "2022-07-26T02:00:00+00:00",
    "2022-07-26T03:00:00+00:00",
    "2022-07-26T04:00:00+00:00",
    "2022-07-26T05:00:00+00:00",
    "2022-07-26T06:00:00+00:00",
    "2022-07-26T07:00:00+00:00",
    "2022-07-26T08:00:00+00:00",
    "2022-07-26T09:00:00+00:00",
    "2022-07-26T10:00:00+00:00",
    "2022-07-26T11:00:00+00:00",
    "2022-07-26T12:00:00+00:00",
    "2022-07-26T13:00:00+00:00",
    "2022-07-26T14:00:00+00:00",
    "2022-07-26T15:00:00+00:00",
    "2022-07-26T16:00:00+00:00",
    "2022-07-26T17:00:00+00:00",
    "2022-07-26T18:00:00+00:00",
    "2022-07-26T19:00:00+00:00",
    "2022-07-26T20:00:00+00:00",
    "2022-07-26T21:00:00+00:00",
    "2022-07-26T22:00:00+00:00",
    "2022-07-26T23:00:00+00:00",
]

SEVEN_DAY_ERROR_EVENTS = [
    74,
    532,
    670,
    631,
    552,
    429,
    463,
    489,
    540,
    599,
    536,
    533,
    521,
    1374,
    970,
    756,
    947,
    990,
    687,
    685,
    627,
    789,
    710,
    410,
    450,
    599,
    553,
    693,
    620,
    357,
    490,
    601,
    948,
    1027,
    506,
    601,
    533,
    707,
    879,
    776,
    776,
    580,
    617,
    716,
    771,
    663,
    752,
    301,
    218,
    557,
    600,
    457,
    740,
    608,
    642,
    749,
    1189,
    1390,
    1335,
    1389,
    1033,
    353,
    199,
    120,
    110,
    130,
    117,
    120,
    105,
    174,
    116,
    58,
    307,
    168,
    74,
    184,
    96,
    86,
    92,
    602,
    2194,
    743,
    116,
    116,
    123,
    98,
    235,
    145,
    386,
    172,
    167,
    130,
    144,
    128,
    120,
    125,
    273,
    262,
    307,
    246,
    268,
    315,
    228,
    225,
    301,
    361,
    316,
    604,
    296,
    285,
    600,
    511,
    506,
    392,
    371,
    553,
    464,
    522,
    238,
    295,
    263,
    247,
    189,
    267,
    422,
    252,
    178,
    241,
    285,
    456,
    315,
    273,
    206,
    219,
    594,
    561,
    642,
    585,
    524,
    374,
    353,
    322,
    304,
    245,
    288,
    164,
    818,
    162,
    217,
    293,
    463,
    213,
    270,
    337,
    322,
    631,
    333,
    447,
    1672,
    689,
    642,
    571,
    365,
    414,
    345,
    389,
    354,
    314,
]


def test_spike_case() -> None:
    start_time = datetime.fromisoformat("2022-07-27T00:00:00+00:00")
    ceilings_list = generate_issue_forecast(
        {"intervals": SEVEN_DAY_INPUT_INTERVALS, "data": SEVEN_DAY_ERROR_EVENTS}, start_time
    )
    ceilings = [x["forecasted_value"] for x in ceilings_list]

    assert ceilings == [6987] * 14, "Ceilings are incorrect"


def test_bursty_case() -> None:
    error_events = [
        77,
        162,
        7846,
        8,
        4,
        2,
        3,
        25,
        4,
        24,
        7,
        6,
        3,
        8,
        3,
        157,
        168,
        161,
        7955,
        1,
        10,
        19,
        108,
        155,
        9,
        1,
        166,
        152,
        149,
        6604,
        2,
        6,
        198,
        127,
        182,
        4032,
        1,
        6,
        4,
        198,
        120,
        171,
        3656,
        6,
        4,
        1,
        199,
        150,
        159,
        7113,
        1,
        10,
        3,
        2,
        4,
        2,
        176,
        146,
        174,
        8290,
        6,
        2,
        1,
        1,
        9,
        2,
        6,
        2,
        2,
        174,
        144,
        154,
        7627,
    ] + [0] * 95

    ceilings_list = generate_issue_forecast(
        {"intervals": SEVEN_DAY_INPUT_INTERVALS, "data": error_events}, START_TIME
    )
    ceilings = [x["forecasted_value"] for x in ceilings_list]

    assert ceilings == [16580] * 14, "Ceilings are incorrect"


def test_empty_input() -> None:
    ceilings_list = generate_issue_forecast(
        {"intervals": SEVEN_DAY_INPUT_INTERVALS, "data": []}, START_TIME
    )
    ceilings = [x["forecasted_value"] for x in ceilings_list]

    assert ceilings == [], "Empty Input"


def test_less_than_week_data() -> None:
    error_events = [
        9,
        1,
        166,
        152,
        149,
        6604,
        2,
        6,
        198,
        127,
        182,
        4032,
        1,
        6,
        4,
        198,
        120,
        171,
        3656,
        6,
        4,
        1,
        199,
        150,
        159,
        7113,
        1,
        10,
        3,
        2,
        4,
        2,
        176,
        146,
        174,
        8290,
        6,
        2,
        1,
        1,
        9,
        2,
        6,
        2,
        2,
        174,
        144,
        154,
        7627,
    ] + [0] * 95

    ceilings_list = generate_issue_forecast(
        {"intervals": SIX_DAY_INPUT_INTERVALS, "data": error_events}, START_TIME
    )
    ceilings = [x["forecasted_value"] for x in ceilings_list]

    assert ceilings == [82900] * 14, "Ceilings are incorrect"


def test_low_freq_events() -> None:
    error_events = [6] * 168

    ceilings_list = generate_issue_forecast(
        {"intervals": SEVEN_DAY_INPUT_INTERVALS, "data": error_events}, START_TIME
    )
    ceilings = [x["forecasted_value"] for x in ceilings_list]

    assert ceilings == [36] * 14, "Ceilings are incorrect"


def test_output() -> None:
    ceilings_list = generate_issue_forecast(
        {"intervals": SEVEN_DAY_INPUT_INTERVALS, "data": SEVEN_DAY_ERROR_EVENTS}, START_TIME
    )

    assert ceilings_list == [
        {"forecasted_date": "2022-07-27", "forecasted_value": 6987},
        {"forecasted_date": "2022-07-28", "forecasted_value": 6987},
        {"forecasted_date": "2022-07-29", "forecasted_value": 6987},
        {"forecasted_date": "2022-07-30", "forecasted_value": 6987},
        {"forecasted_date": "2022-07-31", "forecasted_value": 6987},
        {"forecasted_date": "2022-08-01", "forecasted_value": 6987},
        {"forecasted_date": "2022-08-02", "forecasted_value": 6987},
        {"forecasted_date": "2022-08-03", "forecasted_value": 6987},
        {"forecasted_date": "2022-08-04", "forecasted_value": 6987},
        {"forecasted_date": "2022-08-05", "forecasted_value": 6987},
        {"forecasted_date": "2022-08-06", "forecasted_value": 6987},
        {"forecasted_date": "2022-08-07", "forecasted_value": 6987},
        {"forecasted_date": "2022-08-08", "forecasted_value": 6987},
        {"forecasted_date": "2022-08-09", "forecasted_value": 6987},
    ], "output is formatted incorrectly"
